#include "StdAfx.h"
#include "drop_file_helper.h"

UINT WM_IM_DROP_FILE = ::RegisterWindowMessage (_T("WM_IM_DROP_FILE"));

drop_file_helper::drop_file_helper(void)
{
	this->notify_wnd_ = NULL;
}


drop_file_helper::~drop_file_helper(void)
{
}

CString 
drop_file_helper::expand_short_cut(CString &in_file_name)
{
	/// Make sure we have a path
	ASSERT(in_file_name != _T(""));

	CString out_file_name;
	IShellLink* psl;
	HRESULT res;
	LPTSTR lpsz = in_file_name.GetBuffer(MAX_PATH);
	/// Create instance for shell link
	res = ::CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*) &psl);

	if ( SUCCEEDED(res) )
	{
		/// Get a pointer to the persist file interface
		IPersistFile* ppf;
		res = psl->QueryInterface(IID_IPersistFile, (LPVOID*) &ppf);
		if ( SUCCEEDED(res) )
		{
			/// Make sure it's ANSI
			WCHAR wsz[MAX_PATH];
			::MultiByteToWideChar(CP_ACP, 0, lpsz, -1, wsz, MAX_PATH);
			/// Load shortcut
			res = ppf->Load(wsz, STGM_READ);

			if ( SUCCEEDED(res) ) 
			{
				WIN32_FIND_DATA wfd;
				/// find the path from that
				HRESULT res = psl->GetPath(out_file_name.GetBuffer(MAX_PATH), 
					MAX_PATH, &wfd, SLGP_UNCPRIORITY);
				out_file_name.ReleaseBuffer();
			}
			ppf->Release();
		}
		psl->Release();
	}

	in_file_name.ReleaseBuffer();

	/// if this fails, out_file_name == ""
	return out_file_name;
}

void 
drop_file_helper::on_drop_file(HDROP drop_info,BOOL free_handle/* = TRUE*/)
{
	/// Get the number of pathnames that have been dropped
	WORD num_files_dropped = DragQueryFile(drop_info, -1, NULL, 0);

	CString first_file = _T("");

	char * ptr_file = new TCHAR[256*2];	/// handed del
	if ( NULL == ptr_file )
	{
		return;
	}

	/// there may be many, but we'll only use the first
	for( int i = 0; i < num_files_dropped; ++i )
	{
		/// Get the number of bytes required by the file's full pathname
		WORD path_name_size = DragQueryFile(drop_info, i, NULL, 0);
		path_name_size += 1;
		ASSERT(path_name_size < 256*2);
		DragQueryFile(drop_info, i, ptr_file, path_name_size);

		first_file = ptr_file;
		/// if this was a shortcut, we need to expand it to the target path
		CString expanded_file = expand_short_cut(first_file);

		/// if that worked, we should have a real file name
		if ( !expanded_file.IsEmpty() ) 
		{
			first_file = expanded_file;
		}

		if ( notify_wnd_ )
		{
			::SendMessage(notify_wnd_, WM_IM_DROP_FILE, NULL, (LPARAM)(LPCTSTR)first_file);
		}
	}

	delete [] ptr_file; 

	/// Free the memory block containing the dropped-file information
	if ( free_handle )
	{
		DragFinish(drop_info);
	}
}

void 
drop_file_helper::set_notify_wnd(HWND notify_wnd)
{ 
	this->notify_wnd_ = notify_wnd; 
}

/// basic check by fan05